//
// Created by 11510 on 2024/6/12.
//
#include <iostream>
using std::cout;
using std::cin;
using std::endl;


class Data{
public:
    Data(){
    }
    ~Data(){
    }
    int getData() const{
        return _data;
    }

private:
    int _data = 10;
};


class MiddleLayer{
public:
    MiddleLayer(Data * p): _pdata(p){
    }

    ~MiddleLayer(){
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }

    /**
     * 重载->
     * @return
     */
    Data* operator->(){
        return _pdata;
    }

    /**
     * 重载*
     * @return
     */
    Data& operator*(){
        return *_pdata;
    }



private:
    Data * _pdata;
};


class ThirdLayer{
public:
    ThirdLayer(MiddleLayer* ml):_ml(ml){
        printf("ThirdLayer()\n");
    }

    ~ThirdLayer(){
        printf("~ThirdLayer()\n");
        if(_ml){
            delete _ml;
            _ml = nullptr;
        }
    }
    MiddleLayer& operator->(){
        return *_ml;
    }

    /**
     * 目标一
     * 层层解引用
     * @return
     */
#if 0
    MiddleLayer& operator*(){
        return *_ml;
    }
#else

    /**
     * 目标二
     * 一步到位
     */
     Data& operator*(){
        return *(*_ml);
     }
#endif
private:
    MiddleLayer *_ml;
};


void test0(){
//    BUG 错误的创建方式，让thirdLayer的指针指向栈上的对象，执行析构会发生段错误
/*    Data *data = new Data();
    MiddleLayer middleLayer(data);
    ThirdLayer thirdLayer(&middleLayer);*/
    ThirdLayer thirdLayer(new MiddleLayer(new Data()));
#if 0
    /**
     * 目标一：一层一层解引用
     */
    thirdLayer.operator*().operator*().getData();
    cout << (*(*thirdLayer)).getData() << endl;
#else

    /**
     * 目标二：一步到位解引用
     */
    cout <<(*thirdLayer).getData() << endl;
#endif
}


void test1(){
    ThirdLayer thirdLayer(new MiddleLayer(new Data()));
    /**
     * 前一个operator->是thirdlayer的成员函数，返回结果未middlelayer对象
     * 后一个operator->是middlelayer的成员函数，返回结果是Data*
     * 编译器会自动加入一个->，让Data*调用getData()函数
     */
    thirdLayer.operator->().operator->()->getData();// 本质
    cout << thirdLayer->getData() << endl;
}





int main() {
    test0();
    return 0;
}